<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->

<template>
  <div class="log-item flex-h">
    <div
        v-for="(item, index) in columns"
        :key="index"
        :class="item.label"
        @click="selectLog(item.label, data[item.label])"
    >
        <span class="red" v-if="item.label === 'timestamp'">
              {{ dateFormat(data.timestamp) }}
            </span>
      <span class="red" v-else-if="item.label === 'tags'" :class="level.toLowerCase()"> > </span>
      <span class="red" v-else-if="item.label === 'traceId'">
              <el-tooltip content="Trace Link" v-if="!noLink && data[item.label]">
                <Icon iconName="merge"/>
              </el-tooltip>
            </span>
      <span v-else v-html="highlightKeywords(data[item.label],item.label)"></span>

    </div>
  </div>
</template>
<script lang="ts" setup>
import { computed, inject } from "vue";
import { ServiceLogConstants } from "./data";
import getDashboard from "@/hooks/useDashboardsSession";
import { useDashboardStore } from "@/store/modules/dashboard";
import type { LayoutConfig } from "@/types/dashboard";
import { dateFormat } from "@/utils/dateFormat";
import { WidgetType } from "@/views/dashboard/data";
import { useLogStore } from "@/store/modules/log";
const logStore = useLogStore();

/*global defineProps, defineEmits, Recordable */
const props = defineProps({
  data: {type: Object as any, default: () => ({})},
  noLink: {type: Boolean, default: true},
});
const dashboardStore = useDashboardStore();
const options: Recordable<LayoutConfig> = inject("options") || {};
const emit = defineEmits(["select"]);
const columns = ServiceLogConstants;
const level = computed(() => {
  if (!props.data.tags) {
    return "";
  }
  return (props.data.tags.find((d: { key: string; value: string }) => d.key === "level") || {}).value || "";
});
const highlightKeywords = (data: string, label: string) => {
  console.log(`label:`, label)
  if (label !== 'content') {
    return "";
  }


  // TID前面的
// 正则表达式
  const beforeRegex = /([^\[]+)\[TID:[^\]]+\]\s*\[([^\]]+)\]/;

// 替换逻辑
  data = data.replace(beforeRegex, (match, beforeTID, xxPart) => {
    return `<span style="color: #917373; ">${beforeTID}</span>[TID:3446d2292c384a2a9475bc2a6e383b2f.163.17316480301670049] <span style="color: #00a8ff; font-weight: bold">[${xxPart}]</span>`;
  })


  // 匹配所有[]中的内容
  const bracketRegex = /\[([^\]]+)\]/g;
  data = data.replace(bracketRegex, (match) => {
    return `<span style="color: #778beb;" >${match}</span>`;
  });


  // 如果已经包含>部分,则不走{}逻辑
  if (data.indexOf(">") === -1) {
    // 匹配 {XXX}
    let searchValue = matchBraces(data);
    if (searchValue != null) {
      data = data.replace(searchValue, `<span style="color: #e80000;" > ${searchValue}</span>`);
    }
  }

  data = data.replace(/->.*?(\s|$)/g, (match) => {
    return `<span style="color: #ff0035;">${match}</span>`;
  });

  const keywords = Object.values(logStore.conditions.keywordsOfContent || {}).concat(["INFO", "DEBUG", "ERROR"]);
  // 区分大小写匹配
  const regex = new RegExp(keywords.join("|"), "g");

  data = data.replace(regex, (match) => {
    // 根据匹配的内容进行不同的替换
    if (match === "DEBUG") {
      return `<span style="color: #3498db;font-weight: bold" >${match}</span>`;
    } else if (match === "ERROR") {
      return `<span style="color: #ff4757;font-weight: bold">${match}</span>`;
    } else if (match === "WARN") {
      return `<span style="color: #f1c40f;font-weight: bold">${match}</span>`;
    } else if (match === "INFO") {
      // 将 "INFO" 之前的字符用灰色显示
      // const index = data.indexOf(match);
      // const prefix = data.slice(0, index);
      // const rest = data.slice(index + match.length);
      // return `<span style="color: #00ff81">${prefix}</span><span style="color: #278c4b; font-weight: bold">${match}</span>${rest}`;
      return `<span style="color: #278c4b; font-weight: bold">${match}</span>`;
    } else {
      // 判断对应的外层是否已经有
      return `<span style="color: #c0392b;font-weight: bold;font-size: 20px">${match}</span>`; // 其他关键字高亮显示
    }
  });
  return data;
};

/*匹配所有以{}包裹的内容*/
function matchBraces(str: string): string | null {
  let balance = 0;
  let start = -1;
  let result = '';

  for (let i = 0; i < str.length; i++) {
    if (str[i] === '{') {
      if (balance === 0) {
        start = i;
      }
      balance++;
    } else if (str[i] === '}') {
      balance--;
      if (balance === 0) {
        result = str.substring(start, i + 1);
        return result; // 直接返回结果，避免继续遍历
      }
    }
  }

  // 如果没有找到匹配的括号，返回 null
  return null;
}


function selectLog(label: string, value: string) {
  if (label === "traceId") {
    if (!value) {
      emit("select", props.data);
      return;
    }
    linkTrace(value);
    return;
  }
  emit("select", props.data);
}

function linkTrace(id: string) {
  const {associationWidget} = getDashboard(dashboardStore.currentDashboard);
  associationWidget(
      (options.id as any) || "",
      {
        sourceId: options.id || "",
        traceId: id,
        id: props.data.serviceId || "",
      },
      WidgetType.Trace,
  );
}
</script>
<style lang="scss" scoped>
.log-item {
  cursor: pointer;
  align-items: center;
  min-height: 30px;

  .traceId {
    cursor: pointer;
    width: 20px;
    text-align: center;
    position: relative;

    span {
      display: inline-block;
      width: 100%;
    }

    .blue {
      color: var(--el-color-primary);
    }
  }

  .tags {
    width: 15px;
    text-align: center;
    color: var(--sw-green);
    font-weight: 400;
    font-size: 14px;
  }

  .content {
    width: 1300px;
  }

  .serviceName {
    width: 200px;
  }
}

.log-item:hover {
  background: var(--sw-list-hover);
}

.log-item > div {
  width: 60px;
  padding: 0 5px;
  display: inline-block;
  border: 1px solid transparent;
  white-space: normal;
  word-break: break-all;
  overflow: hidden;
}

.log-item .text {
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.log-item > div.method {
  height: 100%;
  padding: 3px 8px;
}

.error {
  color: var(--sw-orange);
}

.warning {
  color: var(--sw-orange);
}
</style>
